package com.youku.utils
{
   import flash.net.NetStream;
   import flash.utils.Dictionary;
   import flash.net.NetStreamAppendBytesAction;
   import flash.net.URLStream;
   import flash.events.Event;
   import flash.events.ProgressEvent;
   import flash.events.HTTPStatusEvent;
   import flash.events.IOErrorEvent;
   import flash.events.SecurityErrorEvent;
   import flash.events.AsyncErrorEvent;
   import flash.net.URLRequest;
   import flash.system.Security;
   import flash.events.NetStatusEvent;
   import flash.utils.ByteArray;
   import flash.net.NetConnection;
   
   public class UrlNetStream extends NetStream
   {
      
      public function UrlNetStream(param1:NetConnection, param2:String = "connectToFMS") {
         super(param1,param2);
         addEventListener(NetStatusEvent.NET_STATUS,this.onNetStatusEvent,false,0,true);
      }
      
      private static var _loadedPolicyAddr:Dictionary = new Dictionary();
      
      override public function get bytesTotal() : uint {
         return uint(this._bytesTotal);
      }
      
      override public function get bytesLoaded() : uint {
         return uint(this._bytesLoaded);
      }
      
      override public function play(... rest) : void {
         if(rest.length == 0)
         {
            throw new Error("UrlNetStream.play() stream name not specified");
         }
         else
         {
            this.stop();
            this._url = rest[0];
            this._status = 0;
            this._bytesTotal = 0;
            this._bytesLoaded = 0;
            if(checkPolicyFile)
            {
               this.loadPolicyFile(this._url);
            }
            super.play(null);
            appendBytesAction(NetStreamAppendBytesAction.RESET_BEGIN);
            this.notifyPlayStart();
            this._stream = new URLStream();
            this._stream.addEventListener(Event.COMPLETE,this.onCompleteEvent);
            this._stream.addEventListener(ProgressEvent.PROGRESS,this.onProgressEvent);
            this._stream.addEventListener(HTTPStatusEvent.HTTP_STATUS,this.onHTTPStatusEvent);
            this._stream.addEventListener(IOErrorEvent.IO_ERROR,this.onIOErrorEvent);
            this._stream.addEventListener(SecurityErrorEvent.SECURITY_ERROR,this.onSecurityErrorEvent);
            this._stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR,this.onAsyncErrorEvent);
            this._stream.load(new URLRequest(this._url));
            return;
         }
      }
      
      override public function close() : void {
         this.stop();
         super.close();
      }
      
      override public function seek(param1:Number) : void {
         throw new Error("UrlNetStream::seek(...) unsupported");
      }
      
      private function stop() : void {
         if(this._stream != null)
         {
            this._stream.removeEventListener(Event.COMPLETE,this.onCompleteEvent);
            this._stream.removeEventListener(ProgressEvent.PROGRESS,this.onProgressEvent);
            this._stream.removeEventListener(HTTPStatusEvent.HTTP_STATUS,this.onHTTPStatusEvent);
            this._stream.removeEventListener(IOErrorEvent.IO_ERROR,this.onIOErrorEvent);
            this._stream.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,this.onSecurityErrorEvent);
            this._stream.removeEventListener(AsyncErrorEvent.ASYNC_ERROR,this.onAsyncErrorEvent);
            try
            {
               this._stream.close();
            }
            catch(error:Error)
            {
            }
            this._stream = null;
         }
      }
      
      private function loadPolicyFile(param1:String) : void {
         var _loc2_:String = null;
         if(param1 != null)
         {
            _loc2_ = param1.split("/")[2];
            if(_loc2_.indexOf(":") == -1)
            {
               _loc2_ = _loc2_ + ":80";
            }
            if(!(_loc2_ in _loadedPolicyAddr))
            {
               _loadedPolicyAddr[_loc2_] = true;
               Security.loadPolicyFile("http://" + _loc2_ + "/crossdomain.xml");
            }
         }
      }
      
      private function onNetStatusEvent(param1:NetStatusEvent) : void {
         if(param1.info.code == "NetStream.Buffer.Empty" && this._bytesLoaded == this._bytesTotal && this._bytesTotal > 0)
         {
            this.notifyPlayStop();
         }
      }
      
      private function onHTTPStatusEvent(param1:HTTPStatusEvent) : void {
         this._status = param1.status;
      }
      
      private function onProgressEvent(param1:ProgressEvent) : void {
         var _loc2_:ByteArray = new ByteArray();
         while(this._stream.bytesAvailable > 0)
         {
            this._stream.readBytes(_loc2_,_loc2_.length);
         }
         if(_loc2_.length > 0)
         {
            appendBytes(_loc2_);
         }
         this._bytesLoaded = this._bytesLoaded + _loc2_.length;
         this._bytesTotal = param1.bytesTotal;
      }
      
      private function onCompleteEvent(param1:Event) : void {
         var _loc2_:ByteArray = new ByteArray();
         while(this._stream.bytesAvailable > 0)
         {
            this._stream.readBytes(_loc2_,_loc2_.length);
         }
         if(_loc2_.length > 0)
         {
            appendBytes(_loc2_);
         }
         this._bytesLoaded = this._bytesLoaded + _loc2_.length;
         this._bytesTotal = Math.max(this._bytesLoaded,this._bytesTotal);
         this.stop();
         if(this._bytesLoaded < this._bytesTotal)
         {
            this.notifyIOError("Unexpected end of URLStream");
         }
         else if(bufferLength == 0)
         {
            this.notifyPlayStop();
         }
         else
         {
            appendBytesAction(NetStreamAppendBytesAction.END_SEQUENCE);
         }
         
      }
      
      private function onIOErrorEvent(param1:IOErrorEvent) : void {
         this.stop();
         if(this._status >= 400)
         {
            this.notifyStreamNotFound();
         }
         else
         {
            this.notifyIOError("ioError on URLStream");
         }
      }
      
      private function onSecurityErrorEvent(param1:SecurityErrorEvent) : void {
         this.stop();
         this.notifyPlayFailed();
      }
      
      private function onAsyncErrorEvent(param1:AsyncErrorEvent) : void {
         this.stop();
         this.notifyIOError("asyncError on URLStream");
      }
      
      private function notifyIOError(param1:String) : void {
         dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR,false,false,param1));
      }
      
      private function notifyPlayStart() : void {
         dispatchEvent(new NetStatusEvent(NetStatusEvent.NET_STATUS,false,false,
            {
               "code":"NetStream.Play.Start",
               "level":"status"
            }));
      }
      
      private function notifyPlayStop() : void {
         dispatchEvent(new NetStatusEvent(NetStatusEvent.NET_STATUS,false,false,
            {
               "code":"NetStream.Play.Stop",
               "level":"status"
            }));
      }
      
      private function notifyPlayFailed() : void {
         dispatchEvent(new NetStatusEvent(NetStatusEvent.NET_STATUS,false,false,
            {
               "code":"NetStream.Play.Failed",
               "level":"error"
            }));
      }
      
      private function notifyStreamNotFound() : void {
         dispatchEvent(new NetStatusEvent(NetStatusEvent.NET_STATUS,false,false,
            {
               "code":"NetStream.Play.StreamNotFound",
               "level":"error"
            }));
      }
      
      private var _stream:URLStream = null;
      
      private var _url:String = null;
      
      private var _status:int = 0;
      
      private var _bytesTotal:Number = 0;
      
      private var _bytesLoaded:Number = 0;
   }
}
